package com.jzit.network

import com.jzit.network.certificate.SSLSocketClient
import com.jzit.network.utils.LogUtils
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import retrofit2.CallAdapter
import retrofit2.Converter
import retrofit2.Retrofit
import java.util.*
import java.util.concurrent.TimeUnit

/*
    ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
       Author   :  zhouxc
       Date     :  2022/10/26
       Time     :  14:40
    ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
 */
object NetWorkFactory {
    private const val NET_LOG: String = "RETROFIT_LOG"
    private val retrofitMap = mutableMapOf<String, Retrofit>()
    private var iNetworkOptions: INetworkOptions = DefaultNetWorkOption()

    fun <T> createService(clazz: Class<T>): T {
        LogUtils.logI(NET_LOG, "1,NetWorkFactory createService ${clazz.simpleName}")
        Objects.requireNonNull(clazz, "class is null")
        var url = ""
        if (clazz.isAnnotationPresent(BaseUrl::class.java)) {
            url = clazz.getAnnotation(BaseUrl::class.java).url
            Objects.requireNonNull(url, "url is null")
        }

        return create(clazz, url)
    }

    private fun <T> create(clazz: Class<T>, url: String): T {
        var retrofit = retrofitMap[url]
        LogUtils.logI(NET_LOG, "2,Create $url  Retrofit $retrofit")
        if (retrofit == null) {
            retrofit = createRetrofit(url).apply {
                retrofitMap[url] = this!!
            }
        }

        return retrofit?.create(clazz)!!
    }

    fun initINetworkOption(iNetworkOptions: INetworkOptions) {
        NetWorkFactory.iNetworkOptions = iNetworkOptions
    }

    private fun createRetrofit(url: String): Retrofit? {
        val builder = Retrofit.Builder().apply {
            LogUtils.logI(NET_LOG, "3,$url")
            baseUrl(url)
            LogUtils.logI(NET_LOG, "4,Start Create Okhttp Client")
            client(getClient())
            var mCallAdapterFactory = ArrayList<CallAdapter.Factory>()
            iNetworkOptions.addCallAdapterFactory(mCallAdapterFactory)
            mCallAdapterFactory.forEach {
                addCallAdapterFactory(it)
            }
            var mConverterFactory = ArrayList<Converter.Factory>()
            iNetworkOptions.addConverterFactory(mConverterFactory)
            mConverterFactory.forEach {
                addConverterFactory(it)
            }

        }
        LogUtils.logI(NET_LOG, "5,Okhttp Client Create Success")
        return builder.build()
    }

    private fun getClient(): OkHttpClient {
        val httpClient = iNetworkOptions.getHttpClient()
        return if (httpClient == null) {
            OkHttpClient.Builder()
        } else {
            httpClient.newBuilder()
        }.apply {
            var mInterceptors = ArrayList<Interceptor>()
            iNetworkOptions.addInterceptor(mInterceptors)
            mInterceptors.forEach {
                addInterceptor(it)
            }
            readTimeout(15, TimeUnit.SECONDS)
            writeTimeout(15, TimeUnit.SECONDS)
            retryOnConnectionFailure(true)
            connectTimeout(15, TimeUnit.SECONDS)
            sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
            hostnameVerifier(SSLSocketClient.getHostnameVerifier())
        }.build()
    }
}